﻿using System;
using web_uchet.Models;
using System.Linq;
using System.Data.Objects;
using System.Collections.Generic;
using Mvc.Validation;
using Mvc.Validation.Validators;
using web_uchet.Security.Enums;
using web_uchet.Security;
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;
//<summary>
//Класс пользователя для операций CRUD из веб интерфейса. Практически 1 в 1 по отношению к Пользователю модели данных
//</summary>
namespace web_uchet.ViewModels
{
    public interface IViewПользователь
    {
        web_uchet.Models.ASPNetUser ASPNetUser { get; set; }
        System.Data.Objects.DataClasses.EntityReference<web_uchet.Models.ASPNetUser> ASPNetUserReference { get; set; }
        string Password1 { get; set; }
        string Password2 { get; set; }
        string Role1 { get; set; }
        string Role2 { get; set; }
        string Role3 { get; set; }
        UserRoleEnum[] Roles { get; }
        string UserName { get; set; }
        System.Data.Objects.DataClasses.EntityCollection<web_uchet.Models.Заказ> ЗаказыВРолиИсполнителя { get; set; }
        System.Data.Objects.DataClasses.EntityCollection<web_uchet.Models.Заказ> ЗаказыВРолиМенеджера { get; set; }
        int ИД_Место_Работы { get; set; }
        int ИД_Пользователя { get; }
        string Имя_Настоящее { get; set; }
        web_uchet.Models.Компания Компания { get; set; }
        System.Data.Objects.DataClasses.EntityReference<web_uchet.Models.Компания> КомпанияReference { get; set; }
        web_uchet.Models.Место_Работы Место_Работы { get; set; }
        System.Data.Objects.DataClasses.EntityReference<web_uchet.Models.Место_Работы> Место_РаботыReference { get; set; }
        string Описание1 { get; set; }
        string Описание2 { get; set; }
        string Описание3 { get; set; }
        web_uchet.Models.Пользователь Пользователь { get; }
    }
    [System.Web.Mvc.Bind(Exclude = "_Password1,_UserName")]
    public class ViewПользователь : IViewПользователь
    {
        private Пользователь _Пользователь;
        public ViewПользователь()
        {
            this._Пользователь = new Пользователь();
        }
        public ViewПользователь(Пользователь Base)
        {
            this._Пользователь = Base;
            if (!this._Пользователь.ASPNetUserReference.IsLoaded)
                this._Пользователь.ASPNetUserReference.Load();

            string[] UsersRoles = System.Web.Security.Roles.GetRolesForUser(this._Пользователь.ASPNetUser.UserName);
            this._Roles = new UserRoleEnum[] { UserRoleEnum.Не_задано, UserRoleEnum.Не_задано, UserRoleEnum.Не_задано };
            for (int i = 0; i < (UsersRoles.Length > 3 ? 3 : UsersRoles.Length); i++)
                this._Roles[i] = (UserRoleEnum)Enum.Parse(typeof(UserRoleEnum), UsersRoles[i]);
        }
        #region IПользователь Members

        public ASPNetUser ASPNetUser
        {
            get
            {
                return this._Пользователь.ASPNetUser;
            }
            set
            {
                this._Пользователь.ASPNetUser = value;
            }
        }

        public System.Data.Objects.DataClasses.EntityReference<ASPNetUser> ASPNetUserReference
        {
            get
            {
                return this._Пользователь.ASPNetUserReference;
            }
            set
            {
                this._Пользователь.ASPNetUserReference = value;
            }
        }

        public System.Data.Objects.DataClasses.EntityCollection<Заказ> ЗаказыВРолиИсполнителя
        {
            get
            {
                return this._Пользователь.ЗаказыВРолиИсполнителя;
            }
            set
            {
                this._Пользователь.ЗаказыВРолиИсполнителя = value;
            }
        }

        public System.Data.Objects.DataClasses.EntityCollection<Заказ> ЗаказыВРолиМенеджера
        {
            get
            {
                return this._Пользователь.ЗаказыВРолиМенеджера;
            }
            set
            {
                this._Пользователь.ЗаказыВРолиМенеджера = value;
            }
        }

        public int ИД_Пользователя
        {
            get
            {
                return this._Пользователь.ИД_Пользователя;
            }
            //set
            //{
            //    this._Пользователь.ИД_Пользователя = value;
            //}
        }        

        public Компания Компания
        {
            get
            {
                return this._Пользователь.Компания;
            }
            set
            {
                this._Пользователь.Компания = value;
            }
        }

        public System.Data.Objects.DataClasses.EntityReference<Компания> КомпанияReference
        {
            get
            {
                return this._Пользователь.КомпанияReference;
            }
            set
            {
                this._Пользователь.КомпанияReference = value;
            }
        }

        public Место_Работы Место_Работы
        {
            get
            {
                return this._Пользователь.Место_Работы;
            }
            set
            {
                this._Пользователь.Место_Работы = value;
            }
        }

        public System.Data.Objects.DataClasses.EntityReference<Место_Работы> Место_РаботыReference
        {
            get
            {
                return this._Пользователь.Место_РаботыReference;
            }
            set
            {
                this._Пользователь.Место_РаботыReference = value;
            }
        }

        [StringLengthValidator(45, MessageTemplate = "Не более 45 символов")]
        [NotNullOrEmptyValidator(MessageTemplate = "Введите ФИО работника")]
        public string Имя_Настоящее
        {
            get
            {
                return this._Пользователь.Имя_Настоящее;
            }
            set
            {
                if (value == null) this._Пользователь.Имя_Настоящее = string.Empty;
                else
                this._Пользователь.Имя_Настоящее = value;
            }
        }
        [StringLengthValidator(45, MessageTemplate = "Не более 45 символов")]
        public string Описание1
        {
            get
            {
                return this._Пользователь.Описание1;
            }
            set
            {
                if (value == null) this._Пользователь.Описание1 = string.Empty;
                else
                    this._Пользователь.Описание1 = value;
            }
        }
        [StringLengthValidator(45, MessageTemplate = "Не более 45 символов")]
        public string Описание2
        {
            get
            {
                return this._Пользователь.Описание2;
            }
            set
            {
                if (value == null) this._Пользователь.Описание2 = string.Empty;
                else
                this._Пользователь.Описание2 = value;
            }
        }
        [StringLengthValidator(45, MessageTemplate = "Не более 45 символов")]
        public string Описание3
        {
            get
            {
                return this._Пользователь.Описание3;
            }
            set
            {
                if (value == null) this._Пользователь.Описание3 = string.Empty;
                else
                    this._Пользователь.Описание3 = value;
            }
        }

        public Пользователь Пользователь { get { return this._Пользователь; } }

        #endregion

        #region IASPNetUser Members
        //[NotNullOrEmptyValidator(MessageTemplate = "Введите имя пользователя")]
        //[RemoteValidator(MessageTemplate = "Такое имя пользователя уже существует, введите другое",
        //ValidatorType = typeof(AlwaysTrueValidator),
        //ServerMethod = "/Account/UserNotExists", IsPost = false)]
        public string UserName
        {
            get
            {
                if (!this._Пользователь.ASPNetUserReference.IsLoaded)
                    this._Пользователь.ASPNetUserReference.Load();
                    return this._Пользователь.ASPNetUser.UserName;
            }
            //set
            //{
            //    if (!this._Пользователь.ASPNetUserReference.IsLoaded)
            //        this._Пользователь.ASPNetUserReference.Load();
            //    this._Пользователь.ASPNetUser.UserName = value;
            //}
            set
            {
                this._UserName = value;
            }
        }
        public string _Password1 = string.Empty;
        private string _Password2 = string.Empty;
        public string _UserName = string.Empty;
        //[RegularExpressionValidator(
        //    MessageTemplate = "Пароль должен содержать хотя бы один не алфавитно цифровой символ, например: $,#,%,^,&,* и т.п.",
        //    Pattern = @"^.*[^a-zA-Z0-9_]{1}.*$")]
        //[StringLengthValidator(7, 20, MessageTemplate = "Длина пароля от 7 до 20 символов,")]
        //[PropertyComparisonValidator("Password2", ComparisonOperator.Equal,
        //    MessageTemplate = "Пароли должны совпадать")]
        //[NotNullOrEmptyValidator(MessageTemplate = "Введите пароль")]
        public string Password1
        {
            get
            {
                return this._Password1;
            }
            set
            {
                if (value == null) this._Password1 = string.Empty;
                else
                this._Password1 = value;
            }
        }
        //[RegularExpressionValidator(
        //    MessageTemplate = "Пароль должен содержать хотя бы один не алфавитно цифровой символ, например: $,#,%,^,&,* и т.п.",
        //    Pattern = @"^.*[^a-zA-Z0-9_]{1}.*$")]
        //[StringLengthValidator(7, 20, MessageTemplate = "Длина пароля от 7 до 20 символов,")]
        //[PropertyComparisonValidator("Password1", ComparisonOperator.Equal,
        //    MessageTemplate = "Пароли должны совпадать")]
        //[NotNullOrEmptyValidator(MessageTemplate = "Введите подтверждение пароля")]
        public string Password2
        {
            get
            {
                return this.Password1;
            }
            set
            {
                if (value == null) this._Password2 = string.Empty;
                else
                this._Password2 = value;
            }
        }
        #endregion
        [NotNullOrEmptyValidator(MessageTemplate = "Выберите место работы")]
        public int ИД_Место_Работы
        {
            get 
            { 
                return Convert.ToInt32(
                this._Пользователь.Место_РаботыReference.EntityKey.EntityKeyValues.First(k => k.Key == "ИД_Места_Работы").Value); 
            }
            set
            {
                this._Пользователь.Место_РаботыReference.EntityKey=
                    new System.Data.EntityKey("ModelWebUchetCon.Места_Работы","ИД_Места_Работы",value);
            }
        }

        private UserRoleEnum[] _Roles;
        public UserRoleEnum[] Roles
        {
            get
            {
                return this._Roles;
                //if (UsersRoles.Contains("Администратор")) return Enum.GetName(typeof(UserRoleEnum), UserRoleEnum.Администратор);
                //if (UsersRoles.Contains("Менеджер")) return Enum.GetName(typeof(UserRoleEnum), UserRoleEnum.Менеджер);
                //if (UsersRoles.Contains("Исполнитель")) return Enum.GetName(typeof(UserRoleEnum), UserRoleEnum.Исполнитель);
                //if (UsersRoles.Contains("Просмотр")) return Enum.GetName(typeof(UserRoleEnum), UserRoleEnum.Просмотр);
                //return Enum.GetName(typeof(UserRoleEnum), UserRoleEnum.UnKnown);
                //throw new ArgumentOutOfRangeException("Пользователь не принадлежит ни одной допустимой роли");                
            }
        }
        [NotNullOrEmptyValidator(MessageTemplate = "Выберите обязанности")]
        public string Role1 {
            get {
                if (this._Roles.Length > 0)
                    return this._Roles[0].ToString();
                else return UserRoleEnum.Не_задано.ToString();
            }
            set
            {
                UserRoleEnum EVal=(UserRoleEnum)Enum.Parse(typeof(UserRoleEnum), value);
                    if (!this._Пользователь.ASPNetUserReference.IsLoaded)
                        this._Пользователь.ASPNetUserReference.Load();
                    
                if (EVal != UserRoleEnum.Не_задано&&!this._Roles.Contains(EVal))
                {
                    if (this._Roles[0]!=UserRoleEnum.Не_задано)
                    System.Web.Security.Roles.RemoveUserFromRole(this._Пользователь.ASPNetUser.UserName, this._Roles[0].ToString());

                    System.Web.Security.Roles.AddUserToRole(this._Пользователь.ASPNetUser.UserName, value);
                }
                else
                    if (this._Roles[0] != UserRoleEnum.Не_задано && EVal == UserRoleEnum.Не_задано)
                        System.Web.Security.Roles.RemoveUserFromRole(this._Пользователь.ASPNetUser.UserName, this._Roles[0].ToString());
                this._Roles[0] = EVal;
            }
        }
        public string Role2 {
            get
            {
                if (this._Roles.Length > 1)
                    return this._Roles[1].ToString();
                else return UserRoleEnum.Не_задано.ToString();
            }
            set
            {
                UserRoleEnum EVal = (UserRoleEnum)Enum.Parse(typeof(UserRoleEnum), value);
                if (!this._Пользователь.ASPNetUserReference.IsLoaded)
                    this._Пользователь.ASPNetUserReference.Load();

                if (EVal != UserRoleEnum.Не_задано && !this._Roles.Contains(EVal))
                {
                    if (this._Roles[1] != UserRoleEnum.Не_задано)
                        System.Web.Security.Roles.RemoveUserFromRole(this._Пользователь.ASPNetUser.UserName, this._Roles[1].ToString());

                    System.Web.Security.Roles.AddUserToRole(this._Пользователь.ASPNetUser.UserName, value);
                }
                else
                    if (this._Roles[1] != UserRoleEnum.Не_задано && EVal == UserRoleEnum.Не_задано)
                        System.Web.Security.Roles.RemoveUserFromRole(this._Пользователь.ASPNetUser.UserName, this._Roles[1].ToString());
                this._Roles[1] = EVal;
            }
        }
        public string Role3 {
            get
            {
                if (this._Roles.Length > 2)
                    return this._Roles[2].ToString();
                else return UserRoleEnum.Не_задано.ToString();
            }
            set
            {
                UserRoleEnum EVal = (UserRoleEnum)Enum.Parse(typeof(UserRoleEnum), value);
                if (!this._Пользователь.ASPNetUserReference.IsLoaded)
                    this._Пользователь.ASPNetUserReference.Load();

                if (EVal != UserRoleEnum.Не_задано && !this._Roles.Contains(EVal))
                {
                    if (this._Roles[2] != UserRoleEnum.Не_задано)
                        System.Web.Security.Roles.RemoveUserFromRole(this._Пользователь.ASPNetUser.UserName, this._Roles[2].ToString());

                    System.Web.Security.Roles.AddUserToRole(this._Пользователь.ASPNetUser.UserName, value);
                }
                else
                    if (this._Roles[2] != UserRoleEnum.Не_задано && EVal == UserRoleEnum.Не_задано)
                        System.Web.Security.Roles.RemoveUserFromRole(this._Пользователь.ASPNetUser.UserName, this._Roles[2].ToString());
                this._Roles[2] = EVal;
            }
        }
    }

    public class ViewПользовательOperationProvider
    {
        private ModelWebUchetCon _Context;

        public ViewПользовательOperationProvider()
        {
            this._Context = new ModelWebUchetCon(ModelWebUchetCon.SingleToneConnection);
        }
        public ViewПользовательOperationProvider(ModelWebUchetCon Context)
        {
            this._Context =Context;
        }

        //v CompanyID - ID компании для которой делаем LIST
        public IEnumerable<ViewПользователь> List(int CompanyID)
        {
            var Users= this._Context.Пользователи.Include("Место_Работы").Where(e => e.Компания.ИД_Компании == CompanyID).ToList();
            Users.Remove(Users.First(e=>e.Имя_Настоящее=="Нет"));    
            return Users.Select(e => new ViewПользователь(e));
        }
        public ViewПользователь Details(int UserID, ProgramContext SecurirtyData)
        {
            ViewПользователь NeededUser = new ViewПользователь(this._Context.Пользователи.Include("Место_Работы").First(e => e.ИД_Пользователя == UserID));
            if (Convert.ToInt32(
                NeededUser.КомпанияReference.EntityKey.EntityKeyValues.First(e => e.Key == "ИД_Компании").Value) == SecurirtyData.CompanyID)
                return NeededUser;
            else throw new System.Security.SecurityException("Попытка получить данные чужой компании");
        }
        //Disable User
        public string Delete(int UserID, ProgramContext SecurirtyData)
        {
            //<Проверка на правильность компании>
             if (Convert.ToInt32(this._Context.Пользователи.First(e => e.ИД_Пользователя == UserID).
                КомпанияReference.EntityKey.EntityKeyValues.First(e => e.Key == "ИД_Компании").Value)!= SecurirtyData.CompanyID)
                 throw new System.Security.SecurityException("Попытка отключить пользователя чужой компании");
            //</>

            System.Web.Security.MembershipUser MUser =System.Web.Security.Membership.GetUser(UserID);
            if (System.Web.Security.Membership.GetUser().UserName == MUser.UserName && MUser.IsApproved)
            {
                System.Web.Security.FormsAuthentication.SignOut();
            }
            MUser.IsApproved = !MUser.IsApproved;
            System.Web.Security.Membership.UpdateUser(MUser);
            if (MUser.IsApproved) return "Пользователь активирован";
            else return "Пользователь отключен";
        }
        public void Update(ViewПользователь User)
        {
            //this._Context.SaveChanges(true);
            if (User._Password1 != string.Empty || User.UserName != string.Empty)
                if (!User.Пользователь.ASPNetUserReference.IsLoaded)
                    User.Пользователь.ASPNetUserReference.Load();
            if (User._Password1 != string.Empty)
            {
                var UserMembership = System.Web.Security.Membership.GetUser(User.Пользователь.ASPNetUser.UserName);
                UserMembership.ChangePassword(
                UserMembership.ResetPassword(), User._Password1);
            }
            if (User._UserName != string.Empty)
            {
                if (System.Web.Security.Membership.GetUser().UserName==
                    User.Пользователь.ASPNetUser.UserName) 
                    System.Web.Security.FormsAuthentication.SetAuthCookie(User._UserName, false);
                User.Пользователь.ASPNetUser.UserName = User._UserName;
            }
            this._Context.SaveChanges(true);
        }
        public void SaveChanges()
        {
            this._Context.SaveChanges(true);
        }

    }
}
